package com.syty.demo.controller;

import com.sun.deploy.net.HttpResponse;
import com.syty.demo.Listener.LoginSessionListener;
import com.syty.demo.domain.User;
import com.syty.demo.exception.MyException;
import com.syty.demo.form.LoginForm;
import com.syty.demo.form.RegisterForm;
import com.syty.demo.form.RemakeForm;
import com.syty.demo.result.ExceptionResultSet;
import com.syty.demo.result.ResultCodes;
import com.syty.demo.result.ResultSet;
import com.syty.demo.service.UserService;
import com.syty.demo.util.LogUtils;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;

@Api("登录处理器")
@Controller
public class UserController {

    @Autowired
    private UserService userService;

    @ApiOperation("跳转登录页面")
    @RequestMapping({"/","/login","/register"})
    public String loginMain(){
        return "loginAndregister";
    }

    @ApiOperation("跳转重置密码页面")
    @RequestMapping("/remake")
    public String remakeMain(){
        return "remakePwd";
    }

    @ApiOperation("登入数据处理器")
    @CrossOrigin(origins = "*")
    @PostMapping("/loginProcessor")
    public String login(@ModelAttribute @Validated LoginForm loginForm, BindingResult bindingResult, HttpSession session,HttpServletResponse response) throws IOException {
        LogUtils.write("[用户登录]--username : "+loginForm.getUsername());
        LogUtils.write("[用户登录]--password : "+loginForm.getPassword());
        LogUtils.write("[用户登录]--开始登录");
        LogUtils.write("[用户登录]--sessionId :"+session.getId());
        //非空校验
        if (bindingResult.hasErrors()){
            LogUtils.write("[用户登录]--信息不能为空");
            throw new MyException(ExceptionResultSet.USER_LOGIN_INFO_NULL);
        }

        //校验是否重复登录
        if (LoginSessionListener.hasLogin(session.getId())) {
            LogUtils.write("[用户登录]--用户重复登录！");
            return "redirect:/toError";
        }

         //验证用户名和密码
        Subject subject = SecurityUtils.getSubject();
        try {
            subject.login(new UsernamePasswordToken(loginForm.getUsername(),loginForm.getPassword()));

        }catch (UnknownAccountException e){
            e.printStackTrace();
            LogUtils.write("[用户登录]--账户错误 :" + loginForm.getUsername());
            response.sendRedirect("/error");
        }catch (IncorrectCredentialsException e){
            e.printStackTrace();
            LogUtils.write("[用户登录]--密码错误 : " + loginForm.getPassword());
            response.sendRedirect("/error");
        }

        ResultSet loginSession = userService.login(loginForm);
        session.setAttribute("user",loginSession);
        LogUtils.write("[用户登录]--存入loginSession ： " + loginSession);
        LogUtils.write("[用户登录]--登录成功");

        // 登录成功，存储session信息
        LoginSessionListener.addSession(session.getId(), session);
//        LoginSessionListener.addSession(loginForm.getUsername(), session);


        response.sendRedirect("/index");
        return null;
    }

    @ApiOperation("登出数据处理器")
    @RequestMapping("/logout")
    public String logout(HttpSession session) {
        Subject subject = SecurityUtils.getSubject();
        String principal = (String) subject.getPrincipal();

        // 判断用户是否已经登录
        if (!LoginSessionListener.hasLogin(session.getId())) {
            LogUtils.write("[用户登出]--当前用户未登录，无需注销！");
        }
        // 移除session信息
        LoginSessionListener.removeSession(session.getId());
        subject.logout();

        return "redirect:/";
    }

    @ApiOperation("注册数据处理器")
    @CrossOrigin(origins = "*")
    @PostMapping("/registerProcessor")
    @ResponseBody
    public ResultSet register(@ModelAttribute @Validated RegisterForm registerForm,BindingResult bindingResult) {
        LogUtils.write("[用户注册]--username : "+registerForm.getRegisterUsername());
        LogUtils.write("[用户注册]--email : "+registerForm.getRegisterEmail());
        LogUtils.write("[用户注册]--password : "+registerForm.getRegisterPassword());
        LogUtils.write("[用户注册]--开始注册");
//        非空校验
        if (bindingResult.hasErrors()){
            LogUtils.write("注册信息不能为空");
            throw new MyException(ExceptionResultSet.USER_REGISTER_INFO_NULL);
        }
        ResultSet register = userService.register(registerForm);
        System.out.println(register);
        if ((!register.getSuccess())||register.getData()==null||register.getResultCode()==ResultCodes.REGISTER_SUBMIT_FAIL){
            LogUtils.write("[用户注册]--添加用户失败！");
            throw new MyException(ExceptionResultSet.USER_REGISTER_ADD_ERROR);
        }
        LogUtils.write("[用户注册]--注册成功");
        return register;
    }

    @ApiOperation("重置密码数据处理器")
    @CrossOrigin(origins = "*")
    @PostMapping("/remakeProcessor")
    @ResponseBody
    public ResultSet remake(@ModelAttribute @Validated RemakeForm remakeForm,BindingResult bindingResult){
        LogUtils.write("[重置密码]--username : "+remakeForm.getUsername());
        LogUtils.write("[重置密码]--email :"+remakeForm.getEmail());
        LogUtils.write("[重置密码]--password : "+remakeForm.getPassword());
        LogUtils.write("[重置密码]--开始重置");
        //        非空校验
        if (bindingResult.hasErrors()){
            LogUtils.write("注册信息不能为空");
            throw new MyException(ExceptionResultSet.USER_REGISTER_INFO_NULL);
        }
        ResultSet remake = userService.remake(remakeForm);
        if ((!remake.getSuccess())||remake.getData()==null||remake.getResultCode()==ResultCodes.REMAKE_SUBMIT_FAIL){
            LogUtils.write("[重置密码]--重置失败！");
            throw new MyException(ExceptionResultSet.USER_REMAKE_ERROR);
        }
        LogUtils.write("[重置密码]--重置成功");
        return remake;
    }
}
